package cn.flying.cloud.core.interceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.time.LocalDateTime;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import cn.flying.cloud.base.common.constants.Constants;
import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.base.core.interceptor.AbstractRequestInterceptor;
import cn.flying.cloud.core.auth.details.UserDetail;
import cn.flying.cloud.core.event.RequestLogEvent;

/**
 * @description: 用户相关信息绑定到当前线程
 * @author: admin
 * @date: 2023年05月27日 12:23
 * @version: 1.0
 */
@Component
public class RequestContextInterceptor extends AbstractRequestInterceptor {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private final ThreadLocal<LocalDateTime> td = new ThreadLocal<>();

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        td.set(LocalDateTime.now());
        String requestUri = request.getRequestURI();
        logger.info("用户详情拦截：【{}】", requestUri);
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetail userDetail;
        if (authentication != null && authentication.isAuthenticated()) {
            userDetail = (UserDetail) authentication.getPrincipal();
            Ft.ThreadLocal.set(Constants.TENANT_ID, userDetail.getTenantId());
            Ft.ThreadLocal.set(Constants.USER_ID, userDetail.getUserId());
            Ft.ThreadLocal.set(Constants.USER_NAME, userDetail.getUsername());
            Ft.ThreadLocal.set(Constants.FULL_NAME, userDetail.getName());
        } else {
            userDetail = new UserDetail();
        }
        Ft.ThreadLocal.set("startTime", LocalDateTime.now());
        logger.info("线程【{}】绑定租户【{}】的用户【{}-{}】信息", Thread.currentThread().getName(), userDetail.getTenantId(), userDetail.getUserId(), userDetail.getUsername());
        return true;
    }


    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        String tenantId = (String) Ft.ThreadLocal.get(Constants.TENANT_ID);
        String userId = (String) Ft.ThreadLocal.get(Constants.USER_ID);
        String userName = (String) Ft.ThreadLocal.get(Constants.USER_NAME);

        Ft.ThreadLocal.remove(Constants.TENANT_ID);
        Ft.ThreadLocal.remove(Constants.USER_ID);
        Ft.ThreadLocal.remove(Constants.USER_NAME);
        Ft.ThreadLocal.remove(Constants.FULL_NAME);
        logger.info("线程【{}】清除租户【{}】的用户【{}-{}】信息", Thread.currentThread().getName(), tenantId, userId, userName);

        if ("/favicon.ico".contains(request.getRequestURI()) || "/error".contains(request.getRequestURI()) || request.getRequestURI().endsWith(".js")) {
            return;
        }
        // 保存访问记录
        RequestLogEvent event = new RequestLogEvent(this);
        event.setTenantId(tenantId);
        event.setUserId(userId);
        event.setUsername(userName);
        event.setIp(Ft.Network.getIpAddress(request));
        event.setUri(request.getRequestURI());
        event.setType(request.getMethod());
        event.setStartTime((LocalDateTime) Ft.ThreadLocal.get("startTime"));
        event.setEndTime(LocalDateTime.now());
        applicationEventPublisher.publishEvent(event);

        Ft.ThreadLocal.remove("startTime");
    }

    /**
     * 设置拦截器的执行顺序，返回值越小优先级越高
     *
     * @return
     */
    @Override
    public Integer getOrder() {
        return Integer.MIN_VALUE;
    }
}
